package web;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import objects.Board;
import objects.Character;
import objects.HypoResult;
import objects.MurderableRoom;
import objects.Room;
import objects.Weapon;
import utils.FactoryUI;
import bl.GameManager;

import com.google.gson.Gson;
import com.google.gson.JsonObject;

/**
 * Servlet implementation class ComputerPlayServlet
 */
@WebServlet(name = "ComputerPlay", urlPatterns =
{
    "/ComputerPlay"
})
public class ComputerPlayServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public ComputerPlayServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
	{
		
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
	{
		response.setContentType("application/json");
	    response.setCharacterEncoding("UTF-8");
		PrintWriter out = response.getWriter();
		out.flush();
		ResultJson rs = new ResultJson();
		// A string builter that summarizes all the actions a computer preformed in his turn.
		StringBuilder stbStory = new StringBuilder();
		Weapon wpnWeap = Weapon.values()[Board.getInstance().randomNumbers(0,Weapon.values().length - 1)];
		Character chrChar = Character.values()[Board.getInstance().randomNumbers(0,Character.values().length - 1)];
		JsonObject jsAction = new JsonObject();	
		jsAction.addProperty("playerType", "COMPUTER");
		String playerName = Board.getInstance().getCurrPlayerInstance().getPlayerName();
		int nChoice;
		nChoice = Board.getInstance().randomNumbers(0, 1);
		nChoice = 0;
		//Assume or accuse?
		if (nChoice == 0) // Assume
		{
			stbStory.append("\n" + playerName + " chose to assume.\n ");
			
			// Computer roll the die.
			int nDieResult = Board.getInstance().randomNumbers(1,6);
			nChoice = Board.getInstance().randomNumbers(0, 1);
			String playerDecision = "Left";
			// Set direction according to random 0 or 1.
			if (nChoice == 0)
			{
				playerDecision = "Right";
			}
			
			// Move nDieResult steps in that direction.
			Board.getInstance().movePlayer(Board.getInstance().getCurrPlayerInstance(), nDieResult, playerDecision.substring(0, 0));
			
		
			// If computer player not in corridor, play
			if (!Board.getInstance().getRoomName(Board.getInstance().getCurrPlayerInstance().getRoomNumber()).equals("CORRIDOR"))
			{
				// Get the current room.
				Room rmRoom = ((MurderableRoom) Board.getInstance().getRooms()[Board.getInstance().getCurrPlayerInstance().getRoomNumber()]).getRoom();
				stbStory.append("\nThe assumption: " + chrChar.name() + " in the " + rmRoom.name() + " with the " + wpnWeap + ".");
				// Make the assumption and get the result.
				HypoResult hr = GameManager.makehypothesis(rmRoom, chrChar, wpnWeap);
				// If there are any contradicting cards:
				if (hr.getCards() != null)
				{
					if(hr.getCards().size() == 1)
					{
						rs.res = "1";
						rs.content = FactoryUI.getShowedContradictHtml(hr.getCards().get(0),hr.getContPlayer().getPlayerName());
						rs.countCard = hr.getCards().size();
						
						jsAction.addProperty("code", "assumeOneCardRes");
						jsAction.addProperty("player", playerName);
						jsAction.addProperty("content", rs.content);
						jsAction.addProperty("contPlayer", hr.getContPlayer().getPlayerName());
						jsAction.addProperty("contCard", hr.getCards().get(0).getName());
						jsAction.addProperty("message", stbStory.toString() + " and was contradicted by "
								+ hr.getContPlayer().getPlayerName()  + "! ");
						Board.getInstance().addJsActions(jsAction);
						EndTurnServlet.turnEnder();
					}
					else if (hr.getCards().size() > 1)
					{
						rs.res = "1";
						rs.content = FactoryUI.getChooseContradictHtml(hr.getCards(),hr.getContPlayer().getPlayerName());
						rs.countCard = hr.getCards().size();
						
						jsAction.addProperty("code", "assumeManyCardsRes");
						jsAction.addProperty("player", playerName);
						jsAction.addProperty("content", rs.content);
						jsAction.addProperty("contPlayer", hr.getContPlayer().getPlayerName());
						jsAction.addProperty("message",stbStory.toString() +  " and was contradicted by " + hr.getContPlayer().getPlayerName() + "! ");
						Board.getInstance().addJsActions(jsAction);
						return;
					}
					else
					{
						rs.res = "2";
						rs.content = "";
						jsAction.addProperty("code", "assumeNoRes");
						jsAction.addProperty("player", playerName);
						jsAction.addProperty("message", stbStory.toString());
						Board.getInstance().addJsActions(jsAction);
						EndTurnServlet.turnEnder();
					}
				}
			}
			else
			{
				jsAction.addProperty("code", "compCorridor");
				jsAction.addProperty("player", playerName);
				jsAction.addProperty("message", "Player " +playerName+ " moved in to the corridor and can not guess!");
				Board.getInstance().addJsActions(jsAction);
				EndTurnServlet.turnEnder();
			}
		}
		else if (nChoice == 1) // Accuse
		{
			int nRoomIdx = Board.getInstance().randomNumbers(0,Room.values().length - 1);
			Room rmRoom = Room.values()[nRoomIdx];
			stbStory.append(playerName + " chose to accuse " + rmRoom.name() + ", " + chrChar.name() + ", " + wpnWeap.name());
			boolean bDidWin = GameManager.winOrLose(rmRoom, chrChar, wpnWeap);
			
			if (bDidWin)
			{
				jsAction.addProperty("code", "win");
				jsAction.addProperty("playerName", playerName);
				jsAction.addProperty("message", "Player " +playerName+ " Is the winner!");
				Board.getInstance().addJsActions(jsAction);
				rs.res = "3";
	
			}
			else
			{
				Board.getInstance().getCurrPlayerInstance().setInTheGame(false);
				Board.getInstance().getCurrPlayerInstance().setReason("disqualified");
				List<String> playerDetails = new ArrayList<String>();
				
				boolean onePlayerLeft = Board.getInstance().onePlayerLeft();
				
				if (Board.getInstance().getNumberOfHumansInGame() == 0)
				{
					onePlayerLeft = true;
				}
				
				jsAction.addProperty("code", "disqualified");
				jsAction.addProperty("player", playerName);
				jsAction.addProperty("hasMorePlayers", !onePlayerLeft);
				jsAction.addProperty("message", "Player " +playerName+ " lost and is out of the game!");
				Board.getInstance().addJsActions(jsAction);
				
				
				Board.getInstance().getCurrPlayerInstance().setInTheGame(false);
				Board.getInstance().getCurrPlayerInstance().setReason("disqualified");
				
				jsAction.addProperty("code", "disqualified");
				jsAction.addProperty("playerName", playerName);
				jsAction.addProperty("message",stbStory + ". Player " +playerName+ " disqualified!");
				EndTurnServlet.turnEnder();
				rs.res = "4";
			}
		}
		
		/*
		String playerOld = Board.getInstance().getCurrPlayerInstance().getPlayerName();
		Board.getInstance().advanceTurn();
		String playerNew = Board.getInstance().getCurrPlayerInstance().getPlayerName();
		
		JsonObject jsAction2 = new JsonObject();
		jsAction2.addProperty("code", "endTurn");
		jsAction2.addProperty("playerOld", playerOld);
		jsAction2.addProperty("playerNew", playerNew);
		jsAction2.addProperty("message", "Player " +playerOld+ " finished his turn. It's " + playerNew + "'s turn to play.");
		Board.getInstance().addJsActions(jsAction2);
		*/
		rs.story = stbStory.toString();
		out.print(new Gson().toJson(rs));
	}
	
	
	public static void CompPlay()
	{
		ResultJson resJs = new ResultJson();
		// A string builter that summarizes all the actions a computer preformed in his turn.
		StringBuilder stbStory = new StringBuilder();
		Weapon wpnWeap = Weapon.values()[Board.getInstance().randomNumbers(0,Weapon.values().length - 1)];
		Character chrChar = Character.values()[Board.getInstance().randomNumbers(0,Character.values().length - 1)];
		JsonObject jsAction = new JsonObject();	
		jsAction.addProperty("playerType", "COMPUTER");
		String playerName = Board.getInstance().getCurrPlayerInstance().getPlayerName();
		int nChoice;
		nChoice = Board.getInstance().randomNumbers(0, 1);
		//Assume or accuse?
		if (nChoice == 0) // Assume
		{
			stbStory.append("\n" + playerName + " chose to assume.\n ");
			
			// Computer roll the die.
			int nDieResult = Board.getInstance().randomNumbers(1,6);
			nChoice = Board.getInstance().randomNumbers(0, 1);
			String playerDecision = "Left";
			// Set direction according to random 0 or 1.
			if (nChoice == 0)
			{
				playerDecision = "Right";
			}
			
			// Move nDieResult steps in that direction.
			Board.getInstance().movePlayer(Board.getInstance().getCurrPlayerInstance(), nDieResult, playerDecision.substring(0, 0));
			
		
			// If computer player not in corridor, play
			if (!Board.getInstance().getRoomName(Board.getInstance().getCurrPlayerInstance().getRoomNumber()).equals("CORRIDOR"))
			{
				// Get the current room.
				Room rmRoom = ((MurderableRoom) Board.getInstance().getRooms()[Board.getInstance().getCurrPlayerInstance().getRoomNumber()]).getRoom();
				stbStory.append("\nThe assumption: " + chrChar.name() + " in the " + rmRoom.name() + " with the " + wpnWeap + ".");
				// Make the assumption and get the result.
				HypoResult hr = GameManager.makehypothesis(rmRoom, chrChar, wpnWeap);
				// If there are any contradicting cards:
				if (hr.getCards() != null)
				{
					if(hr.getCards().size() == 1)
					{
						resJs.res = "1";
						resJs.content = FactoryUI.getShowedContradictHtml(hr.getCards().get(0),hr.getContPlayer().getPlayerName());
						resJs.countCard = hr.getCards().size();
						
						jsAction.addProperty("code", "assumeOneCardRes");
						jsAction.addProperty("player", playerName);
						jsAction.addProperty("content", resJs.content);
						jsAction.addProperty("contPlayer", hr.getContPlayer().getPlayerName());
						jsAction.addProperty("contCard", hr.getCards().get(0).getName());
						jsAction.addProperty("message", stbStory.toString() + " and was contradicted by "
								+ hr.getContPlayer().getPlayerName()  + "! ");
						Board.getInstance().addJsActions(jsAction);
						EndTurnServlet.turnEnder();
					}
					else if (hr.getCards().size() > 1)
					{
						resJs.res = "1";
						resJs.content = FactoryUI.getChooseContradictHtml(hr.getCards(),hr.getContPlayer().getPlayerName());
						resJs.countCard = hr.getCards().size();
						
						jsAction.addProperty("code", "assumeManyCardsRes");
						jsAction.addProperty("player", playerName);
						jsAction.addProperty("content", resJs.content);
						jsAction.addProperty("contPlayer", hr.getContPlayer().getPlayerName());
						jsAction.addProperty("message",stbStory.toString() +  " and was contradicted by " + hr.getContPlayer().getPlayerName() + "! ");
						Board.getInstance().addJsActions(jsAction);
						return;
					}
					else
					{
						resJs.res = "2";
						resJs.content = "";
						jsAction.addProperty("code", "assumeNoRes");
						jsAction.addProperty("player", playerName);
						jsAction.addProperty("message", stbStory.toString());
						Board.getInstance().addJsActions(jsAction);
						EndTurnServlet.turnEnder();
					}
				}
			}
			else
			{
				jsAction.addProperty("code", "compCorridor");
				jsAction.addProperty("player", playerName);
				jsAction.addProperty("message", "Player " +playerName+ " moved in to the corridor and can not guess!");
				Board.getInstance().addJsActions(jsAction);
				EndTurnServlet.turnEnder();
			}
		}
		else if (nChoice == 1) // Accuse
		{
			int nRoomIdx = Board.getInstance().randomNumbers(0,Room.values().length - 1);
			Room rmRoom = Room.values()[nRoomIdx];
			stbStory.append(playerName + " chose to accuse " + rmRoom.name() + ", " + chrChar.name() + ", " + wpnWeap.name());
			boolean bDidWin = GameManager.winOrLose(rmRoom, chrChar, wpnWeap);
			
			if (bDidWin)
			{
				jsAction.addProperty("code", "win");
				jsAction.addProperty("playerName", playerName);
				jsAction.addProperty("message", "Player " +playerName+ " Is the winner!");
				Board.getInstance().addJsActions(jsAction);
				resJs.res = "3";
	
			}
			else
			{
				Board.getInstance().getCurrPlayerInstance().setInTheGame(false);
				Board.getInstance().getCurrPlayerInstance().setReason("disqualified");
				List<String> playerDetails = new ArrayList<String>();
				
				boolean onePlayerLeft = Board.getInstance().onePlayerLeft();
				
				if (Board.getInstance().getNumberOfHumansInGame() == 0)
				{
					onePlayerLeft = true;
				}
				
				jsAction.addProperty("code", "disqualified");
				jsAction.addProperty("player", playerName);
				jsAction.addProperty("hasMorePlayers", !onePlayerLeft);
				jsAction.addProperty("message", "Player " +playerName+ " lost and is out of the game!");
				Board.getInstance().addJsActions(jsAction);
				
				
				Board.getInstance().getCurrPlayerInstance().setInTheGame(false);
				Board.getInstance().getCurrPlayerInstance().setReason("disqualified");
				
				jsAction.addProperty("code", "disqualified");
				jsAction.addProperty("playerName", playerName);
				jsAction.addProperty("message",stbStory + ". Player " +playerName+ " disqualified!");
				EndTurnServlet.turnEnder();
				resJs.res = "4";
			}
		}
		
		/*
		String playerOld = Board.getInstance().getCurrPlayerInstance().getPlayerName();
		Board.getInstance().advanceTurn();
		String playerNew = Board.getInstance().getCurrPlayerInstance().getPlayerName();
		
		JsonObject jsAction2 = new JsonObject();
		jsAction2.addProperty("code", "endTurn");
		jsAction2.addProperty("playerOld", playerOld);
		jsAction2.addProperty("playerNew", playerNew);
		jsAction2.addProperty("message", "Player " +playerOld+ " finished his turn. It's " + playerNew + "'s turn to play.");
		Board.getInstance().addJsActions(jsAction2);
		*/
		resJs.story = stbStory.toString();
	}
	
	
	@SuppressWarnings("unused")
    private static class ResultJson {
        private String res;
        private String content;
        private int	   countCard;
        private String story;
    }  
}
